package com.wantupai.mvp.framework.base.adapter;

import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListAdapter;

import com.wantupai.mvp.framework.base.adapter.viewholder.SmartViewHolder;
import com.wantupai.mvp.framework.base.adapter.viewholder.base.ItemViewDelegate;
import com.wantupai.mvp.framework.base.adapter.viewholder.base.ItemViewDelegateManager;

import java.util.ArrayList;
import java.util.List;



/**
 * @author :Created by zhangqing on 2018/5/15 15:49.
 * @description :万能的BaseAdapter
 * @email :1423118197@qq.com
 * @classpath : cn.doolii.mvp.framework.base.adapter.BaseRecyclerAdapter
 */
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<SmartViewHolder> implements ListAdapter
{

    protected final Context mContext;
    private List<T> mList;
    protected OnItemClickListener<T> mOnItemClickListener;
    private ItemViewDelegateManager mItemViewDelegateManager;


    public OnItemClickListener getOnItemClickListener()
    {
        return mOnItemClickListener;
    }

    protected final Context getContext()
    {
        return mContext;
    }

    public BaseRecyclerAdapter(Context context)
    {
        setHasStableIds(false);
        mContext = context;
        this.mList = new ArrayList<T>();
        mItemViewDelegateManager = new ItemViewDelegateManager();
    }

    public BaseRecyclerAdapter addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate)
    {
        mItemViewDelegateManager.addDelegate(itemViewDelegate);
        return this;
    }

    private boolean useItemViewDelegateManager()
    {
        return mItemViewDelegateManager.getItemViewDelegateCount() > 0;
    }

    @Override
    public int getViewTypeCount()
    {
        if (useItemViewDelegateManager())
        {
            return mItemViewDelegateManager.getItemViewDelegateCount();
        }
        return 1;
    }

    @Override
    public int getItemViewType(int position)
    {
        if (!useItemViewDelegateManager())
        {
            return super.getItemViewType(position);
        }
        return mItemViewDelegateManager.getItemViewType(mList.get(position), position);
    }


    @Override
    public SmartViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(viewType);
        int layoutId = itemViewDelegate.getItemViewLayoutId();
        SmartViewHolder holder = SmartViewHolder.get(mContext, parent, layoutId);
        setListener(parent, holder, viewType);
        return holder;
    }

    @Override
    public void onBindViewHolder(SmartViewHolder holder, int position)
    {
        convert(holder, mList.get(position), position);
    }


    @Override
    public int getItemCount()
    {
        return mList.size();
    }


    private final DataSetObservable mDataSetObservable = new DataSetObservable();

    @Override
    public void registerDataSetObserver(DataSetObserver observer)
    {
        mDataSetObservable.registerObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer)
    {
        mDataSetObservable.unregisterObserver(observer);
    }

    public void notifyListDataSetChanged()
    {
        mDataSetObservable.notifyChanged();
    }

    public void notifyDataSetInvalidated()
    {
        mDataSetObservable.notifyInvalidated();
    }

    @Override
    public boolean areAllItemsEnabled()
    {
        return true;
    }

    @Override
    public boolean isEnabled(int position)
    {
        return true;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ItemViewDelegate itemViewDelegate = mItemViewDelegateManager.getItemViewDelegate(mList.get(position), position);
        int layoutId = itemViewDelegate.getItemViewLayoutId();
        SmartViewHolder viewHolder = SmartViewHolder.get(mContext, convertView, parent, layoutId, position);
        convert(viewHolder, getItem(position), position);
        setListener(parent, viewHolder, getItemViewType(position));
        return viewHolder.getConvertView();
    }

    private void convert(SmartViewHolder viewHolder, T item, int position)
    {
        mItemViewDelegateManager.convert(viewHolder, item, position);
    }


    @Override
    public boolean isEmpty()
    {
        return getCount() == 0;
    }


    @Override
    public T getItem(int position)
    {
        if (position < 0 || position > mList.size())
        {
            throw new IndexOutOfBoundsException("下标越界了");
        }
        return mList.get(position);
    }

    @Override
    public int getCount()
    {
        return mList.size();
    }


    private void setListener(final ViewGroup parent, final SmartViewHolder viewHolder, int viewType)
    {
        if (parent instanceof AbsListView)
        {
            return;
        }
        if (!isEnabled(viewType))
        {
            return;
        }
        viewHolder.getConvertView().setOnClickListener(v->{
            if (mOnItemClickListener != null)
            {
                int position = viewHolder.getItemPosition();
                if (position < 0 || position >= getCount())
                {
                    return;
                }
                mOnItemClickListener.onItemClick(mContext, v, viewHolder, mList.get(position), position);
            }
        });
        viewHolder.getConvertView().setOnLongClickListener(v ->
        {
            if (mOnItemClickListener != null)
            {
                int position = viewHolder.getItemPosition();
                if (position < 0 || position >= getCount())
                {
                    return false;
                }
                mOnItemClickListener.onItemLongClick(mContext, v, viewHolder, mList.get(position), position);
                return true;
            }
            return false;
        });
    }

    public void refreshAdapter(boolean isDownToRefresh, List<T> dates)
    {
        //isDownToRefresh：是否是下拉刷新，如果是下拉刷新，则清除数据在添加，否则直接添加
        if (isDownToRefresh)
        {
            mList.clear();
        }
        if (dates != null && !dates.isEmpty())
        {
            mList.addAll(dates);
            notifyDataSetChanged();
        }
    }

    public interface OnItemClickListener<T>
    {
        void onItemClick(Context context, View view, SmartViewHolder holder, T t, int position);

        boolean onItemLongClick(Context context, View view, RecyclerView.ViewHolder holder, T t, int position);
    }


    public void setOnItemClickListener(OnItemClickListener<T> onItemClickListener)
    {
        this.mOnItemClickListener = onItemClickListener;
    }

    public List<T> getLists()
    {
        List<T> list = new ArrayList<>(mList.size());
        for (int i = 0, count = mList.size(); i < count; i++)
        {
            list.add(mList.get(i));
        }
        return list;
    }

    public void updatePosition(int position, T t)
    {
        mList.set(position, t);
        notifyItemChanged(position);
        //notifyDataSetChanged();
    }

    public T remove(int position)
    {
        T remove = mList.remove(position);
        //notifyItemRemoved(position);
        //notifyItemRangeChanged(0, getItemCount());
        notifyDataSetChanged();
        return remove;
    }

    public void add(int position, T t)
    {
        mList.add(position, t);
        notifyItemInserted(position);
        notifyItemRangeChanged(position, getItemCount());
        notifyDataSetChanged();
    }

    public void add(List<T> data)
    {
        if (data == null || data.isEmpty())
        {
            return;
        }
        mList.addAll(data);
        notifyDataSetChanged();
    }

    public void clean()
    {
        mList.clear();
        notifyDataSetChanged();
    }

    public void add(T t)
    {
        add(mList.size(), t);
    }
}
